内存映射UART
简介
此示例将采用先前 示例 中实现的 UartCtrl 组件来创建内存映射UART控制器。
规范
该实现将基于带有RX FIFO的APB3总线。
这是寄存器映射表:
| 名称 | 类型 | 访问 | 地址 | 描述 | 
|---|---|---|---|---|
| clockDivider | UInt | RW | 0 | 设置UartCtrl时钟分频器 | 
| frame | UartCtrlFrameConfig | RW | 4 | 设置数据长度、奇偶校验和停止位配置 | 
| writeCmd | 位 | W | 8 | 向UartCtrl发送写命令 | 
| writeBusy | Bool | R | 8 | 当可以发送新的writeCmd时,位0 => 0 | 
| read | Bool / Bits | R | 12 | 位7到0 => rx payload 位31 => rx payload valid | 
实现
此实现将使用Apb3SlaveFactory工具。它允许您使用良好的语法定义APB3从端。您可以在 这里 找到该工具的文档。
首先,我们只需要定义控制器要使用的 Apb3Config。它在Scala object中被定义为一个函数,以便能够从任何地方获取它。
object Apb3UartCtrl {
  def getApb3Config = Apb3Config(
    addressWidth = 4,
    dataWidth    = 32
  )
}
然后我们可以定义一个 Apb3UartCtrl 组件,该组件实例化了一个 UartCtrl 并在它和APB3总线之间创建内存映射逻辑:
case class Apb3UartCtrl(uartCtrlConfig: UartCtrlGenerics, rxFifoDepth: Int) extends Component {
  val io = new Bundle {
    val bus =  slave(Apb3(Apb3UartCtrl.getApb3Config))
    val uart = master(Uart())
  }
  // Instantiate an simple uart controller
  val uartCtrl = new UartCtrl(uartCtrlConfig)
  io.uart <> uartCtrl.io.uart
  // Create an instance of the Apb3SlaveFactory that will then be used as a slave factory drived by io.bus
  val busCtrl = Apb3SlaveFactory(io.bus)
  // Ask the busCtrl to create a readable/writable register at the address 0
  // and drive uartCtrl.io.config.clockDivider with this register
  busCtrl.driveAndRead(uartCtrl.io.config.clockDivider,address = 0)
  // Do the same thing than above but for uartCtrl.io.config.frame at the address 4
  busCtrl.driveAndRead(uartCtrl.io.config.frame,address = 4)
  // Ask the busCtrl to create a writable Flow[Bits] (valid/payload) at the address 8.
  // Then convert it into a stream and connect it to the uartCtrl.io.write by using an register stage (>->)
  busCtrl.createAndDriveFlow(Bits(uartCtrlConfig.dataWidthMax bits),address = 8).toStream >-> uartCtrl.io.write
  // To avoid losing writes commands between the Flow to Stream transformation just above,
  // make the occupancy of the uartCtrl.io.write readable at address 8
  busCtrl.read(uartCtrl.io.write.valid,address = 8)
  // Take uartCtrl.io.read, convert it into a Stream, then connect it to the input of a FIFO of 64 elements
  // Then make the output of the FIFO readable at the address 12 by using a non blocking protocol
  // (Bit 7 downto 0 => read data <br> Bit 31 => read data valid )
  busCtrl.readStreamNonBlocking(uartCtrl.io.read.queue(rxFifoDepth),
                                address = 12, validBitOffset = 31, payloadBitOffset = 0)
}
重要
是的,仅此而已。它同样是可综合的。
Apb3SlaveFactory工具不是硬编码到SpinalHDL编译器中的东西。它是使用SpinalHDL常规的硬件描述语法实现的。